/*
 * Copyright 2009-2019 the original author or authors  
 *
 */
package com.livery.liu.dao.ibatis;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.util.Assert;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.livery.liu.util.Page;

/**
 * ibatis的基本模板类
 * <pre class="code">
 *  
 * </pre>
 * @author  <a href="mailto:livery.liu@gmail.com"> livery liu</a>
 */
@SuppressWarnings("unchecked")
public class IBatisGenricDaoTemplate extends SqlMapClientDaoSupport{
	
	/**
	 * 通过传入配置文件中对应的名称得到查询结果集
	 * @param String  getList : 
	 * @param T po	: 按对象属性查询
	 * @return List : 返回记录集
	 * 
	 */	
	public <T> List<T> getList(String getList,T po){
		return getSqlMapClientTemplate().queryForList(getList,po);
	}
	
	/**
	 * 通过传入配置文件中对应的名称得到查询结果集
	 * @param String  getListByMap : 
	 * @param T po	: 按对象属性查询
	 * @return List : 返回记录集
	 * 
	 */	
	public <T> List<T> getList(String getListByMap,Map<String,Object> map){
		return getSqlMapClientTemplate().queryForList(getListByMap,map);
	}
	
	/**
	 * 通过传入配置文件中对应的名称得到查询结果对象
	 * @param String  getById : 查询语句定义的名称
	 * @param Map map: 查询的条件对象	 
	 * @return 单个对象
	 * 
	 */	
	public <T> T getById(String getById,Map<String,Object> map){
		return (T)getSqlMapClientTemplate().queryForObject(getById, map);
	}

	
	/**
	 * 通过传入配置文件中对应的名称得到查询结果对象
	 * @param String  getById : 查询语句定义的名称
	 * @param Serializable id: 查询的条件对象	 
	 * @return 单个对象
	 * 
	 */	
	public <T> T getById(String getById,Serializable id){
		return (T)getSqlMapClientTemplate().queryForObject(getById, id);
	}
	/**
	 * 通过传入配置文件中对应的名称得到插入对象
	 * @param String  saveSql :定义的名称
	 * @param po 	: 对象	 
	 * @return T : 返回成功后的对象
	 * 
	 */	
	public <T> T save(String saveSql,T po){
		return (T)getSqlMapClientTemplate().insert(saveSql, po);
	}	
	
	/**
	 * 通过传入配置文件中对应的名称得到更新对象
	 * @param String  updateSql  update的sql语句
	 * @param  T po	: 对象	 
	 * @return 返回是否成功
	 * 
	 */	
	public <T> int update(String updateSql,T po){
		return getSqlMapClientTemplate().update(updateSql, po);
	}	
	

	/**
	 * 通过id删除对象(真实删除)
	 * @param String  queryName :定义的名称
	 * @param queryObj Object	:条件对象	 
	 * @return int :返回是否成功
	 * 
	 */	
	public int delete(String deleteSql,Serializable id){
		return getSqlMapClientTemplate().delete(deleteSql, id);
	}	
	
	/**
	 * 批量插入数据
	 * (自己处理事务)需要进一步验证??
	 * （通过spring的话已经不太需要，只需要配置自动事务来对所有的事务进行管理）
	 * @param String  saveSql : save语句
	 * @param list pos	: 条件对象集合
	 * @return boolean : 返回是否成功
	 * @throws SQLException 
	 */		
    public <T> int saveBatch(String saveSql,List<T> pos) throws SQLException{ 
		SqlMapClient sqlmap = getSqlMapClient();
		sqlmap.startBatch();
		for (T po : pos) {
			sqlmap.insert(saveSql, po);
		}
		int i = sqlmap.executeBatch();
		return i;
    } 
    
	/**
	 * 批量更新数据
	 * 
	 * @param String updateSql : update语句
	 * @param list pos : 对象集合
	 * @return boolean : 返回是否成功
	 * @throws SQLException 
	 */		
    public <T> int updateBatch(String updateSql,List<T> pos) throws SQLException{ 
		SqlMapClient sqlmap = getSqlMapClient();
		sqlmap.startBatch();
		for (T po : pos) {
			sqlmap.update(updateSql, po);
		}
		int i = sqlmap.executeBatch();
		return i;
    } 
	
	/**
	 * 分页查询语句<p>
	 * 需要传入查询语句和同样条件的查询数量的语句
	 * @param <T> 泛型结果
	 * @param querySql 查询语句 （命名空间+sql名称）
	 * @param queryCountSql 同样条件的查询数量的语句 （命名空间+sql名称）
	 * @param params 查询参数组合
	 * @param pageNo >=1 当前页数
	 * @param pageSize 每页的记录数量
	 * @return 分页结果
	 */
	public <T> Page<T> getPageBySqlmap(String querySql, String queryCountSql, Map<String,Object> params, int pageNo, int pageSize) {
		
		Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
		// 计算记录总数
		Integer totalCount = (Integer)getSqlMapClientTemplate().queryForObject(queryCountSql, params);
		// 如果没有数据则返回Empty Page
		Assert.notNull(totalCount, "totalCount Error");
		if (totalCount.intValue() == 0) {
			return new Page<T>();
		}
		int totalPageCount = 0;
		int startIndex = 0;
		Assert.isTrue(pageSize > 0, "pageSize should bigger than 0");
		// 计算总页数
		totalPageCount = (totalCount + pageSize -1)/pageSize;
		
		// 计算skip数量
		pageNo = (pageNo>totalPageCount?totalPageCount:pageNo);
		startIndex = (pageNo - 1) * pageSize + 1;
		
		params.put("begin", startIndex);
		params.put("end", startIndex + pageSize-1);
		
		List<T> list = getSqlMapClientTemplate().queryForList(querySql, params);
		return new Page<T>(startIndex, totalCount, pageSize, list);
	} 
	
}
